package com.dao;

import com.util.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * @author 徐洲
 * @version 1.0
 * 开发 BasicDAO , 是其他 DAO 的父类, 使用到 apache-dbutils
 */
public class BasicDAO<T> { //泛型指定具体类型
    private QueryRunner queryRunner = new QueryRunner();
    private JDBCUtilsByDruid db = new JDBCUtilsByDruid();

    private Connection connection;

    /**
     * 事务
     */
    public boolean transactionUpdate(String[] sqls, Object... parameters){
        // 将 connection 设置为不自动提交, 即开启事务
        try {
            connection = db.getConnection();
            connection.setAutoCommit(false);
            int res = 0;
            for (int i = 0; i < sqls.length; i++) {
                res = queryRunner.update(connection, sqls[i], parameters);
            }
            if (res == 0){
                return false;
            }
            //这里提交事务
            connection.commit();
            return true;
        } catch (SQLException e) {
            // 进行回滚，即撤销执行的sql语句
            try {
                connection.rollback();
                return false;
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
//            throw new RuntimeException(e);
        } finally {
            db.close(null, null, connection);
        }
    }

    /**
     * 批处理
     */


    //开发通用的 dml 方法, 针对任意的表
    public Integer update(String sql, Object... parameters){
        connection = null;
        try {
            connection = db.getConnection();
            return queryRunner.update(connection, sql, parameters);
        }catch (SQLException e){
            throw new RuntimeException(e);
        }finally {
            db.close(null, null, connection);
        }
    }

    /**
     * 返回多个对象(即查询的结果是多行)，针对任意表
     * @param sql sql 语句，可以有？
     * @param clazz 传入一个类的 Class 对象 比如 User.class
     * @param parameters 传入 ？ 的具体值，可以是多个
     * @return 根据 User.class 返回对应的 ArrayList 集合
     */
    public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters){
        connection = null;
        try {
            connection = db.getConnection();
            return  queryRunner.query(connection, sql, new BeanListHandler<T>(clazz), parameters);
        }catch (SQLException e){
            throw new RuntimeException(e);
        }finally {
            db.close(null, null, connection);
        }
    }

    //查询单行结果
    public T querySingle(String sql, Class<T> clazz, Object... parameters){
        connection = null;
        try {
            connection = db.getConnection();
            return  queryRunner.query(connection, sql, new BeanHandler<T>(clazz), parameters);
        }catch (SQLException e){
            throw new RuntimeException(e);
        }finally {
            db.close(null,null,connection);
        }
    }

    //查询单行单列的结果
    public Object queryScalar(String sql, Object... parameters){
        connection = null;
        try {
            connection = db.getConnection();
            return  queryRunner.query(connection, sql, new ScalarHandler(), parameters);
        }catch (SQLException e){
            throw new RuntimeException(e);
        }finally {
            db.close(null, null, connection);
        }
    }
}
